package com.jeesite.modules.utils;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.banboocloud.Codec.Sm3Signature;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.UUID;

/**
 * @author dbl
 * @describe
 * @date 2023年03月15日 11:17
 */
public class SM3Utils {

    private static final String ENCODING = "UTF-8";

    /**
     * 加密
     *
     * @param src 明文
     * @param key 密钥
     * @return
     * @throws Exception
     */
    public static String encrypt(String src, String key) throws Exception {
        return ByteUtils.toHexString(getEncryptByKey(src, key));
    }


    /**
     * SM3加密方式之： 根据自定义密钥进行加密，返回加密后长度为32位的16进制字符串
     *
     * @param src 源数据
     * @param key 密钥
     * @return
     * @throws Exception
     */
    public static byte[] getEncryptByKey(String src, String key) throws Exception {
        byte[] srcByte = src.getBytes(ENCODING);
        byte[] keyByte = key.getBytes(ENCODING);
        KeyParameter keyParameter = new KeyParameter(keyByte);
        SM3Digest sm3 = new SM3Digest();
        HMac hMac = new HMac(sm3);
        hMac.init(keyParameter);
        hMac.update(srcByte, 0, srcByte.length);
        byte[] result = new byte[hMac.getMacSize()];
        hMac.doFinal(result, 0);
        return result;
    }

    /**
     * 利用源数据+密钥校验与密文是否一致
     *
     * @param src       源数据
     * @param key       密钥
     * @param sm3HexStr 密文
     * @return
     * @throws Exception
     */
    public static boolean verify(String src, String key, String sm3HexStr) throws Exception {
        byte[] sm3HashCode = ByteUtils.fromHexString(sm3HexStr);
        byte[] newHashCode = getEncryptByKey(src, key);
        return Arrays.equals(newHashCode, sm3HashCode);
    }

    /**
     * SM3加密方式之：不提供密钥的方式 SM3加密，返回加密后长度为64位的16进制字符串
     *
     * @param src 明文
     * @return
     */
    public static String encrypt(String src) {
        return ByteUtils.toHexString(getEncryptBySrcByte(src.getBytes()));
    }

    /**
     * 返回长度为32位的加密后的byte数组
     *
     * @param srcByte
     * @return
     */
    public static byte[] getEncryptBySrcByte(byte[] srcByte) {
        SM3Digest sm3 = new SM3Digest();
        sm3.update(srcByte, 0, srcByte.length);
        byte[] encryptByte = new byte[sm3.getDigestSize()];
        sm3.doFinal(encryptByte, 0);
        return encryptByte;
    }


    /**
     * 校验源数据与加密数据是否一致
     *
     * @param src       源数据
     * @param sm3HexStr 16进制的加密数据
     * @return
     * @throws Exception
     */
    public static boolean verify(String src, String sm3HexStr) throws Exception {
        byte[] sm3HashCode = ByteUtils.fromHexString(sm3HexStr);
        byte[] newHashCode = getEncryptBySrcByte(src.getBytes(ENCODING));
        return Arrays.equals(newHashCode, sm3HashCode);
    }


    public static void main(String[] args) throws Exception {
//        String srcStr = "今天天气很晴朗";
//        String key = "zjqzjq";
//        // ******************************自定义密钥加密及校验*****************************************
//        String hexStrByKey = SM3Utils.encrypt(srcStr, key);
//        System.out.println("带密钥加密后的密文：" + hexStrByKey);
//
//        System.out.println("明文(带密钥)与密文校验结果：" + SM3Utils.verify(srcStr, key, hexStrByKey));
//
//        // ******************************无密钥的加密及校验******************************************
//        String hexStrNoKey = SM3Utils.encrypt(srcStr);
//        System.out.println("不带密钥加密后的密文：" + hexStrNoKey);
//
//        System.out.println("明文(不带密钥)与密文校验结果：" + SM3Utils.verify(srcStr, hexStrNoKey));


        //获取时间戳timestamp
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        Date date = new Date();
        String timestamp = dateFormat.format(date);
        System.out.println("timestamp:"+timestamp);
//
//        //获取sm
//        String sm = UUID.randomUUID().toString().replace("-","");
//        System.out.println("sm:"+sm);
//
//        //甲方提供reqkey
        String reqkey = "ee5dc0232ea30ce1ae82e01abaf224e5";
//        System.out.println("reqkey:"+reqkey);
//
//        //vcode   SM3(reqkey + “:” +reqsecret + “:”+ sm + “:”+ uri+ “:”+ timestamp)
//
        String reqsecret = "6184eb48874b4dbfacf8b6405d12c77d";
        String uri = "moap/restful/todo/settingPendingInfo/put";
//        String vcode = SM3Utils.encrypt(reqkey+":"+reqsecret+":"+sm+":"+uri+":"+timestamp);
//        System.out.println("vcode:"+vcode);

        String passid = "wzt_to_yth";
        String token = "GVI5JJVaJnv4I5ytlPqzlYHcOhZjjXOF";
        String nonce = UUID.randomUUID().toString().replace("-","");
        String sm = nonce;
        long l = System.currentTimeMillis()/1000;
        System.out.println("timestamp:"+l);
        System.out.println("sm:"+nonce);
        //sha256(x-rio-timestamp + Token + x-rio-nonce + x-rio-timestamp)

        String originalString = l+token+nonce+l;

        MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
        messageDigest.update(originalString.getBytes());
        byte[] result = messageDigest.digest();

        StringBuilder hexString = new StringBuilder();
        for (byte b : result) {
            hexString.append(String.format("%02X", b));
        }

        System.out.println("SHA-256 Hash: " + hexString.toString().toLowerCase());


    }

    public static String getSHA256StrJava(String str){
        MessageDigest messageDigest;
        String encodeStr = "";
        try {
            messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.update(str.getBytes("UTF-8"));
            encodeStr = byte2Hex(messageDigest.digest());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return encodeStr;
    }
    /**
     * 将byte转为16进制
     * @param bytes
     * @return
     */
    private static String byte2Hex(byte[] bytes){
        StringBuffer stringBuffer = new StringBuffer();
        String temp = null;
        for (int i=0;i<bytes.length;i++){
            temp = Integer.toHexString(bytes[i] & 0xFF);
            if (temp.length()==1){
                //1得到一位的进行补0操作
                stringBuffer.append("0");
            }
            stringBuffer.append(temp);
        }
        return stringBuffer.toString();
    }

    /**
     * 根据字符串获取SHA-256加密
     * @return
     */
    public static String getsha256(String str){
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.update(str.getBytes());
            byte[] result = messageDigest.digest();

            StringBuilder hexString = new StringBuilder();
            for (byte b : result) {
                hexString.append(String.format("%02X", b));
            }

            return hexString.toString().toLowerCase();
        }catch(Exception e){
            return "";
        }
    }
}
